/// 《Rust 程序设计语言》第三章 常见编程概念
fn main() {
    // Ⅰ 变量
    rust_variable();
    // Ⅱ constants 常量
    rust_constants();
    // Ⅲ Shadowing 隐藏
    rust_shadowing();
    // Ⅳ 数据类型
    data_type();
    // Ⅴ 函数
    another_function();
    // Ⅵ 控制流
    control_stream();
}


// Ⅰ 变量
fn rust_variable() {
    /// 使用 let 语句来创建变量
    /// 使用 mut 声明变量可变
    let apples = 5;
    let mut guess = String::new();
    guess.push_str("Hello mut guess");
    println!("{}", guess);
    println!("{}", &guess);
}


// Ⅱ constants 常量
fn rust_constants() {
    /// 首先，不允许对常量使用 mut。常量不光默认不可变，它总是不可变。声明常量使用 const 关键字而不是 let，并且 必须 注明值的类型
    const TWO_HOURS_IN_SECONDS: u32 = 60 * 60 * 2;
}


// Ⅲ Shadowing 隐藏
fn rust_shadowing() {
    /// 我们可以定义一个与之前变量同名的新变量。Rustacean 们称之为第一个变量被第二个 隐藏（Shadowing） 了，这意味着当您使用变量的名称时，编译器将看到第二个变量。
    /// 实际上，第二个变量“遮蔽”了第一个变量，此时任何使用该变量名的行为中都会视为是在使用第二个变量，直到第二个变量自己也被隐藏或第二个变量的作用域结束。
    ///
    /// 隐藏与将变量标记为 mut 是有区别的。当不小心尝试对变量重新赋值时，如果没有使用 let 关键字，就会导致编译时错误。
    /// 通过使用 let，我们可以用这个值进行一些计算，不过计算完之后变量仍然是不可变的，如下 :
    /// let spaces = "  ";
    /// spaces = "Hello World";   // 会编译错误！！！
    ///
    /// mut 与隐藏的另一个区别是，当再次使用 let 时，实际上创建了一个新变量，我们可以改变值的类型，并且复用这个名字。
    let spaces = "  ";
    let spaces = spaces.len();
    println!("{}", spaces);
}



// Ⅳ 数据类型
fn data_type() {
    /// 在 Rust 中，每一个值都属于某一个 数据类型（data type），这告诉 Rust 它被指定为何种数据，以便明确数据处理方式。
    /// 我们将看到两类数据类型子集：标量（scalar）和复合（compound）。
    // 标量类型
    /// Rust 有四种基本的标量类型：整型、浮点型、布尔类型、字符类型。
    let numb: i32 = 3;
    let numb: f32 = -3.3;
    let f: bool = false;
    let z: char = 'Z';
    // 复合类型
    /// 复合类型（Compound types）可以将多个值组合成一个类型。Rust 有两个原生的复合类型：元组（tuple）和数组（array）。
    /// 元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定：一旦声明，其长度不会增大或缩小。
    let tup: (i32, f64, u8) = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("解构元组的值: {} {} {}", x, y, z);
    println!("通过索引取值: {} {} {}", tup.0, tup.1, tup.2);

    let array = [1, 2, 3, 4, 5];
    println!("数组的值:{:?}", array);

    let mut vec = Vec::new();
    vec.push(21);
    vec.push(97);
    vec.push(76);
    println!("Vec动态数组的值:{:?}", vec);
    println!("长度: {}, 容量: {}", vec.len(), vec.capacity());
}


// Ⅴ 函数
fn another_function() {
    /// Rust 代码中的函数和变量名使用 snake case 规范风格
    println!("Another function.");
    let y = 6;
    // 语句
    /// (let y = 6); 是一个语句，语句并不返回值，所以不能给变量赋值，如下：
    /// let x = (let y = 6); // 编译将会报错
    // 表达式
    /// 表达式会计算出一个值，并且你将编写的大部分 Rust 代码是由表达式组成的。
    /// 如下: { let x = 3; x + 1 } 这就是一个表达式。
    let y = {
        let x = 3;
        x + 1
    };
    println!("The value of y is: {y}");
    // 具有返回值的函数
    /// 函数可以向调用它的代码返回值。我们并不对返回值命名，但要在箭头（->）后声明它的类型。如下:
    fn five() -> i32 {
        5
    }
    let f = five();
    let i = plus_one(f);
    println!("{}", i);
}
fn plus_one(x: i32) -> i32 {
    x + 3
}


// Ⅵ 控制流
fn control_stream() {
    let number = 3;
    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}




